﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows.Media;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using BasicallyNot.CodeTransformers;
using BasicallyNot.CodeTransformers.Transformers;


namespace BasicallyNot.Classifiers
{

	#region Classification type

	internal static class MemberTypeClassificationDefinition
	{

		/// <summary>
		/// Defines the "MemberTypeClassifier" classification type.
		/// </summary>
		[Export( typeof( ClassificationTypeDefinition ) )]
		[Name( "MemberTypeClassifier" )]
		internal static ClassificationTypeDefinition MemberTypeClassifierType = null;

	}

	#endregion // Classification type



	#region Provider definition

	/// <summary>
	/// This class causes a classifier to be added to the set of classifiers. Since 
	/// the content type is set to "text", this classifier applies to all text files
	/// </summary>
	[Export( typeof( IClassifierProvider ) )]
	[ContentType( "Basic" )]
	internal class MemberTypeClassifierProvider : IClassifierProvider
	{

		/// <summary>
		/// Import the classification registry to be used for getting a reference
		/// to the custom classification type later.
		/// </summary>
		[Import]
		internal IClassificationTypeRegistryService ClassificationRegistry = null; // Set via MEF

		public IClassifier GetClassifier( ITextBuffer buffer )
		{
			return buffer.Properties.GetOrCreateSingletonProperty<MemberTypeClassifier>( delegate { return new MemberTypeClassifier( ClassificationRegistry ); } );
		}

	}

	#endregion // Provider definition

	#region Format

	/// <summary>
	/// Defines an editor format for the MemberTypeClassifier type that has a purple background
	/// and is underlined.
	/// </summary>
	[Export( typeof( EditorFormatDefinition ) )]
	[ClassificationType( ClassificationTypeNames = "MemberTypeClassifier" )]
	[Name( "MemberTypeClassifier" )]
	[UserVisible( true )] //this should be visible to the end user
	[Order( After = Priority.Default )] //set the priority to be after the default classifiers
	//[Order( After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text )]
	internal sealed class MemberTypeClassifierFormat : ClassificationFormatDefinition
	{

		/// <summary>
		/// Defines the visual format for the "MemberTypeClassifier" classification type
		/// </summary>
		public MemberTypeClassifierFormat()
		{
			this.DisplayName = "BasicallyNot - Member Types"; // human readable version of the name
			this.ForegroundColor = Color.FromRgb( 0xFF, 0x00, 0x64 );
		}

	}

	#endregion // Format



	#region Classifier
	/// <summary>
	/// Classifier that classifies all text as an instance of the MemberTypeClassifier
	/// </summary>
	class MemberTypeClassifier : IClassifier
	{

		IClassificationType _classificationType;

		internal MemberTypeClassifier( IClassificationTypeRegistryService registry )
		{
			_classificationType = registry.GetClassificationType( "MemberTypeClassifier" );
		}

		/// <summary>
		/// This method scans the given SnapshotSpan for potential matches for this classification.
		/// In this instance, it classifies everything and returns each span as a new ClassificationSpan.
		/// </summary>
		/// <param name="span">The span currently being classified</param>
		/// <returns>A list of ClassificationSpans that represent spans identified to be of this classification</returns>
		public IList<ClassificationSpan> GetClassificationSpans( SnapshotSpan span )
		{
			return MemberTypeDeducer.GetClassificationSpans( span, _classificationType );
		}

#pragma warning disable 67
		// This event gets raised if a non-text change would affect the classification in some way,
		// for example typing /* would cause the classification to change in C# without directly
		// affecting the span.
		public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
#pragma warning restore 67

	}
	#endregion // Classifier

}
